﻿using EBA.IoC;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;

namespace EBA.Framework
{
    /// <summary>
    /// 进程内插件，只支持动态安装，但不可动态卸载和更新。
    /// </summary>
    [Export("BundleContext", typeof(IBundleContext))]
    public class BundleContext : MarshalByRefObject, IBundleContext
    {

        IContainer _Container;


        /// <summary>
        /// Default container instance
        /// </summary>
        IContainer Container
        {
            get
            {
                if (_Container == null)
                {
                    _Container = new ContainerConfiguration()
                        .WithAssemblies(WindowsAssembly.GetAssemblies(this.StartupPath, "*.dll"))
                        .CreateContainer();
                }

                return _Container;
            }
        }

        /// <summary>
        /// 默认的上下文名称
        /// </summary>
        public static string DefaultName { get { return "BundleContext"; } }

        /// <summary>
        /// 名称
        /// </summary>
        public string Name
        {
            get { return DefaultName; }
        }

        /// <summary>
        /// 关联的插件
        /// </summary>
        public IBundle Bundle
        {
            get;
            set;
        }

        Dictionary<Type, object> Services = new Dictionary<Type, object>();
        /// <summary>
        /// 注册服务实例
        /// </summary>
        /// <typeparam name="TService"></typeparam>
        /// <param name="service"></param>
        public void RegisterService<TService>(TService service)
        {
            var serviceType = typeof(TService);
            this.Services[serviceType] = service;
        }

        /// <summary>
        /// 获取注册的服务实例
        /// </summary>
        /// <typeparam name="TService"></typeparam>
        /// <returns></returns>
        public TService GetService<TService>()
        {
            var serviceType = typeof(TService);
   
            if (this.Services.ContainsKey(serviceType))
            {
                return (TService)this.Services[serviceType];
            }
            else
            {

                throw new ServiceUnregisteredException(serviceType);
            }
        }

        string StartupPath { get; set; }
        /// <summary>
        /// 初始化上下文
        /// </summary>
        /// <param name="bundleRuntimeName"></param>
        /// <param name="startupPath"></param>
        /// <param name="bundleId"></param>
        public void Initialize<TBundle>(string bundleRuntimeName, string startupPath, string bundleId) where TBundle:IBundle
        {
            this.StartupPath = startupPath;
            this.Bundle = this.Container.GetExport<TBundle>(bundleId);
            this.Bundle.StartupPath = startupPath;
            this.Bundle.BundleContext = this;
        }


        #region Dispose

        private bool _Disposed = false;
        ~BundleContext()
        {
            Dispose(false);
        }

        public void Dispose()
        {
            Dispose(true);
        }

        private void Dispose(bool disposing)
        {
            if (!_Disposed)
            {
                if (disposing)
                {
                    GC.SuppressFinalize(this);
                }
                _Disposed = true;
            }
        }

        public override object InitializeLifetimeService()
        {
            return null;
        }
        #endregion
    }
}
